#include "Common/Patterns/SubscriberPublisher.hh"

#include <boost/foreach.hpp>
#include <boost/bind.hpp>

using namespace Common::Patterns;

void Publisher::attach( Subscriber::Ptr aSubscriber )
{
	iSubscribers.push_back( Subscriber::WeakPtr( aSubscriber ) );
}

bool SubscriberEqualWeakPtr( Subscriber::WeakPtr aWeakPtr, Subscriber::Ptr aPtr )
{
	Subscriber::Ptr ptr;

	if ( ptr = aWeakPtr.lock() )
	{
		return ( ptr == aPtr );
	}

	return false;
}

void Publisher::detach( Subscriber::Ptr aSubscriber )
{
	std::list< Subscriber::WeakPtr >::iterator toRemove;

	toRemove = std::remove_if( iSubscribers.begin(), iSubscribers.end(), boost::bind( &SubscriberEqualWeakPtr, _1, aSubscriber ) );

	iSubscribers.erase( toRemove, iSubscribers.end() );

	detachDeletedSubscribers();
}

void Publisher::notifySubscribers()
{
	BOOST_FOREACH( Subscriber::WeakPtr subscriberWeakPtr, iSubscribers )
	{
		if ( Subscriber::Ptr subscriber = subscriberWeakPtr.lock() )
		{
			subscriber->notify();
		}
	}

	detachDeletedSubscribers();
}

void Publisher::detachDeletedSubscribers()
{
	std::list< Subscriber::WeakPtr >::iterator toRemove;

	toRemove = std::remove_if( iSubscribers.begin(), iSubscribers.end(), boost::bind( &Subscriber::WeakPtr::expired, _1 ) );

	iSubscribers.erase( toRemove, iSubscribers.end() );
}
